﻿using System;
using System.Collections.Generic;
using System.DrawingCore;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace StorageBox
{
    using MySize = StorageBox.Size;
    using DrawPoint = System.DrawingCore.Point;
    public class DesktopReader : ReaderViewBase
    {
        private ScrollViewer Scroll;
        private Canvas RootElement;
        private int[][] MatrixArr;
        private Dictionary<int, ApplyElement> _elementList = new();
        private Dictionary<int, System.Windows.Media.Brush> ColorDict = new Dictionary<int, System.Windows.Media.Brush>();

        public DesktopReader(MainWindow main) : base(main)
        {
            RootElement = main.StorageBox_Canvas;
            Scroll = main.StorageBox_Scroll;
        }

        public override void Hide()
        {

        }

        public override void Show()
        {
            var dispFile = BoxApplication.GetManager<DispositionManager>()._disposition;

            MatrixArr = InitializeMatrix(
                new Size() { Width = Convert.ToInt32(RootElement.ActualWidth), Height = Convert.ToInt32(RootElement.ActualHeight) },
                ApplyStaticData.MinSideLength,
                ApplyStaticData.Marage);

            _elementList.Clear();

            //默认
            if (dispFile.IsApplyAdd is 1)
            {
                CreateDefaultApply();
            }

            var applyDataList = dispFile.AppltDataLists;
            foreach (var item in applyDataList)
            {
                var element = ElementFactoryManager.Create<ApplyElement, ApplyData>(item);
                //获取方位
                var point = GetPoint(ref MatrixArr, 0, 0, element.SideLength);
                if (point.X != -1)
                {
                    element.Location = point;
                    SetMatrix(ref MatrixArr, point, element);
                    _elementList.Add(element.PlaceholderKey, element);
                }
            }
            ProtractDood(_elementList.GetValues());
            SetRootElementHeight(MatrixArr);
        }

        public void ShowItem(ApplyData data)
        {
            var manager = BoxApplication.GetManager<DispositionManager>();
            manager.AddApplyData(data);
            manager.WriteDispoition();

            var element = ElementFactoryManager.Create<ApplyElement, ApplyData>(data);
            //显示出来
            var point = GetPoint(ref MatrixArr, 0, 0, data.Langth);
            if (point.X != -1)
            {
                element.Location = point;
                SetMatrix(ref MatrixArr, point, element);
                _elementList.Add(element.PlaceholderKey, element);
            }

            ProtractDood(element);
            SetRootElementHeight(MatrixArr);
        }

        /// <summary>
        /// 创建默认元素
        /// </summary>
        private void CreateDefaultApply()
        {
            MySize size = new() { Width = 1, Height = 1 };
            var point = GetPoint(ref MatrixArr, 0, 0, size);
            if (point.X != -1)
            {
                SetMatrix(ref MatrixArr, point, size, -1);

                Border border = new()
                {
                    Width = ApplyStaticData.MinSideLength.Width,
                    Height = ApplyStaticData.MinSideLength.Height,
                    Margin = new(point.X * (ApplyStaticData.Marage + ApplyStaticData.MinSideLength.Width) + ApplyStaticData.Marage, point.Y * (ApplyStaticData.Marage + ApplyStaticData.MinSideLength.Height) + ApplyStaticData.Marage, 0, 0),
                    BorderThickness = new(2),
                    BorderBrush = SY_Library.Color.BackColor(0),
                    Background = SY_Library.Color.BackColor(255, 255, 255, 255 / 2),
                    Cursor = Cursors.Hand,
                    ContextMenu = BoxApplication.GetManager<ContextMenuManager>().CreateMenuByMainWindow()
                };
                TextBlock tb = new()
                {
                    FontSize = 32.5,
                    TextAlignment = TextAlignment.Center,
                    Text = "+",
                };

                border.MouseLeftButtonDown += _mainWindow.DefaultApplyAdd_MouseDown;
                border.MouseLeftButtonUp += _mainWindow.DefaultApplyAdd_MouseUp;
                border.Child = tb;
                RootElement.Children.Add(border);
                //item.RootElement.Margin = new Thickness(item.Location.X * (ApplyStaticData.Marage + ApplyStaticData.MinSideLength.Width) + ApplyStaticData.Marage, item.Location.Y * (ApplyStaticData.Marage + ApplyStaticData.MinSideLength.Height) + ApplyStaticData.Marage, 0, 0);
            }
        }

        public ApplyElement GetApplyByKey(int key)
        {
            return _elementList.FirstOrDefault(u => u.Key == key).Value;
        }





        /// <summary>
        /// 复写矩阵
        /// </summary>
        private static void SetMatrix(ref int[][] arr, DrawPoint point, ApplyElement dood)
        {
            var X = point.X;
            var Y = point.Y;
            for (int i = 0; i < dood.SideLength.Width * dood.SideLength.Height; i++)
            {
                arr[Convert.ToInt32(Y)][Convert.ToInt32(X)] = dood.PlaceholderKey;

                X++;
                if (X >= dood.SideLength.Width + point.X)
                {
                    X = point.X;
                    Y++;
                }
            }
        }
        private static void SetMatrix(ref int[][] arr, DrawPoint point, MySize size, int key)
        {
            var X = point.X;
            var Y = point.Y;
            for (int i = 0; i < size.Width * size.Height; i++)
            {
                arr[Convert.ToInt32(Y)][Convert.ToInt32(X)] = key;

                X++;
                if (X >= size.Width + point.X)
                {
                    X = point.X;
                    Y++;
                }
            }
        }
        /// <summary>
        /// 更改根元素高度
        /// </summary>
        private void SetRootElementHeight(int[][] arr)
        {
            RootElement.Height = arr.Length * (ApplyStaticData.MinSideLength.Height + ApplyStaticData.Marage) + ApplyStaticData.Marage;
            _mainWindow.Width = arr[0].Length * (ApplyStaticData.MinSideLength.Width + ApplyStaticData.Marage) + ApplyStaticData.Marage;
            Scroll.Width = arr[0].Length * (ApplyStaticData.MinSideLength.Width + ApplyStaticData.Marage) + ApplyStaticData.Marage + 18;
        }
        /// <summary>
        /// 渲染
        /// </summary>
        private void ProtractDood(List<ApplyElement> list)
        {
            if (list is null)
                return;
            foreach (var item in list)
            {
                item.RootElement.Background = GetColorByKey(item.PlaceholderKey);
                item.RootElement.Margin = new Thickness(item.Location.X * (ApplyStaticData.Marage + ApplyStaticData.MinSideLength.Width) + ApplyStaticData.Marage, item.Location.Y * (ApplyStaticData.Marage + ApplyStaticData.MinSideLength.Height) + ApplyStaticData.Marage, 0, 0);
                RootElement.Children.Add(item.RootElement);
            }
        }
        private void ProtractDood(ApplyElement element)
        {
            element.RootElement.Background = GetColorByKey(element.PlaceholderKey);
            element.RootElement.Margin =
                new Thickness(
                    element.Location.X * (ApplyStaticData.Marage + ApplyStaticData.MinSideLength.Width) + ApplyStaticData.Marage,
                    element.Location.Y * (ApplyStaticData.Marage + ApplyStaticData.MinSideLength.Height) + ApplyStaticData.Marage,
                    0, 0);
            RootElement.Children.Add(element.RootElement);
        }
        /// <summary>
        /// 获取颜色
        /// </summary>
        private System.Windows.Media.Brush GetColorByKey(int key)
        {
            if (ColorDict.ContainsKey(key))
            {
                return ColorDict[key];
            }
            else
            {
                Random r = new Random();
                var color = SY_Library.Color.BackColor(Convert.ToByte(r.Next(0, 256)), Convert.ToByte(r.Next(0, 256)), Convert.ToByte(r.Next(0, 256)), 100);
                ColorDict.Add(key, color);
                return color;
            }
        }
        /// <summary>
        /// 初始化矩阵
        /// </summary>
        private int[][] InitializeMatrix(MySize matrixSize, MySize minDoodSize, int Marage)
        {
            var length01 = (matrixSize.Height - Marage) / (minDoodSize.Height + Marage);
            var length02 = (matrixSize.Width - Marage) / (minDoodSize.Width + Marage);
            int[][] arr = new int[length01][];
            for (int i = 0; i < length01; i++)
            {
                arr[i] = new int[length02];
            }
            return arr;
        }
        /// <summary>
        /// 获取方位
        /// </summary>
        private static DrawPoint GetPoint(ref int[][] arr, int x, int y, MySize count)
        {
            if (count.Width > arr[0].Length)
            {
                return new DrawPoint(-1, -1);
            }
            if (x >= arr[0].Length)
            {
                return new DrawPoint(-1, -1);
            }
            if (y >= arr.Length)
            {
                return new DrawPoint(-1, -1);
            }
            var time = DateTime.Now;
            //while (time.AddSeconds(5) >= DateTime.Now)
            while (true)
            {
                if (arr[y][x] == 0)
                {
                    //判断当前空间是否足够
                    var judge = true;
                    //当前行的余位
                    if (x + count.Width > arr[0].Length)
                    {
                        judge = false;
                    }
                    //当前列的余位
                    if (y + count.Height > arr.Length)
                    {
                        //添加行
                        //查询缺少几行
                        var num = y + 1 + count.Height - arr.Length;
                        //添加高度
                        var newArr = new int[arr.Length + num][];
                        //初始化新行
                        for (int i = arr.Length - 1; i < newArr.Length; i++)
                        {
                            newArr[i] = new int[arr[0].Length];
                        }
                        for (int i = 0; i < arr.Length; i++)
                        {
                            newArr[i] = arr[i];
                        }
                        arr = newArr;
                    }
                    for (int i = x; i < x + count.Width && judge; i++)
                    {
                        for (int j = y; j < y + count.Height; j++)
                        {
                            if (arr[j][i] != 0)
                            {
                                judge = false;
                            }
                        }
                    }
                    if (judge)
                    {
                        return new DrawPoint(x, y);
                    }
                }

                //这个地方有人了
                x++;
                if (x >= arr[0].Length)
                {
                    x = 0;
                    y++;

                    if (y >= arr.Length)
                    {
                        //加一行
                        var newArr = new int[arr.Length + 1][];
                        newArr[arr.Length] = new int[arr[0].Length];
                        for (int i = 0; i < arr.Length; i++)
                        {
                            newArr[i] = arr[i];
                        }
                        arr = newArr;
                    }


                }
            }
            return new DrawPoint(-1, -1);
        }


        /// <summary>
        /// 渲染空格
        /// </summary>
        private void ProtractDoodByEmpty(int[][] arr)
        {
            var EmptyList = new ApplyElement[arr.Length][];
            for (int i = 0; i < arr.Length; i++)
            {
                EmptyList[i] = new ApplyElement[arr[i].Length];
            }

            for (int i = 0; i < arr.Length; i++)
            {
                for (int j = 0; j < arr[0].Length; j++)
                {
                    if (arr[i][j] == 0)
                    {
                        //var element = new ApplyElement(0, new() { Width = 1, Height = 1 });
                        //element.Location = new Point(j, i);
                        //element.RootElement.Background = SY_Library.Color.BackColor(0, 100);
                        //element.RootElement.Margin = new Thickness(element.Location.X * (DoodData.Marage + DoodData.MinSideLength.Width) + DoodData.Marage, element.Location.Y * (DoodData.Marage + DoodData.MinSideLength.Height) + DoodData.Marage, 0, 0);

                        //StorageBox_Canvas.Children.Add(element.RootElement);
                        //EmptyList[i][j] = element;
                    }
                }
            }
        }
    }
}
